mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-14 06:57:35 +08:00
add asset trends in statistics & analysis (#314)
This commit is contained in:
+66
-1
@@ -340,7 +340,7 @@ func (a *TransactionsApi) TransactionReconciliationStatementHandler(c *core.WebC
|
||||
minTransactionTime = utils.GetMinTransactionTimeFromUnixTime(reconciliationStatementRequest.StartTime)
|
||||
}
|
||||
|
||||
transactionsWithAccountBalance, totalInflows, totalOutflows, openingBalance, closingBalance, err := a.transactions.GetAllTransactionsWithAccountBalanceByMaxTime(c, uid, pageCountForAccountStatement, maxTransactionTime, minTransactionTime, reconciliationStatementRequest.AccountId, account.Category)
|
||||
transactionsWithAccountBalance, totalInflows, totalOutflows, openingBalance, closingBalance, err := a.transactions.GetAllTransactionsInOneAccountWithAccountBalanceByMaxTime(c, uid, pageCountForAccountStatement, maxTransactionTime, minTransactionTime, reconciliationStatementRequest.AccountId, account.Category)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(c, "[transactions.TransactionReconciliationStatementHandler] failed to get transactions from \"%d\" to \"%d\" for user \"uid:%d\", because %s", reconciliationStatementRequest.StartTime, reconciliationStatementRequest.EndTime, uid, err.Error())
|
||||
@@ -532,6 +532,71 @@ func (a *TransactionsApi) TransactionStatisticsTrendsHandler(c *core.WebContext)
|
||||
return statisticTrendsResp, nil
|
||||
}
|
||||
|
||||
// TransactionStatisticsAssetTrendsHandler returns transaction statistics asset trends of current user
|
||||
func (a *TransactionsApi) TransactionStatisticsAssetTrendsHandler(c *core.WebContext) (any, *errs.Error) {
|
||||
var statisticAssetTrendsReq models.TransactionStatisticAssetTrendsRequest
|
||||
err := c.ShouldBindQuery(&statisticAssetTrendsReq)
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[transactions.TransactionStatisticsAssetTrendsHandler] parse request failed, because %s", err.Error())
|
||||
return nil, errs.NewIncompleteOrIncorrectSubmissionError(err)
|
||||
}
|
||||
|
||||
utcOffset, err := c.GetClientTimezoneOffset()
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[transactions.TransactionStatisticsAssetTrendsHandler] cannot get client timezone offset, because %s", err.Error())
|
||||
return nil, errs.ErrClientTimezoneOffsetInvalid
|
||||
}
|
||||
|
||||
uid := c.GetCurrentUid()
|
||||
|
||||
maxTransactionTime := int64(0)
|
||||
|
||||
if statisticAssetTrendsReq.EndTime > 0 {
|
||||
maxTransactionTime = utils.GetMaxTransactionTimeFromUnixTime(statisticAssetTrendsReq.EndTime)
|
||||
}
|
||||
|
||||
minTransactionTime := int64(0)
|
||||
|
||||
if statisticAssetTrendsReq.StartTime > 0 {
|
||||
minTransactionTime = utils.GetMinTransactionTimeFromUnixTime(statisticAssetTrendsReq.StartTime)
|
||||
}
|
||||
|
||||
accountDailyBalances, err := a.transactions.GetAllAccountsDailyOpeningAndClosingBalance(c, uid, maxTransactionTime, minTransactionTime, utcOffset)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(c, "[transactions.TransactionStatisticsAssetTrendsHandler] failed to get transactions from \"%d\" to \"%d\" for user \"uid:%d\", because %s", statisticAssetTrendsReq.StartTime, statisticAssetTrendsReq.EndTime, uid, err.Error())
|
||||
return nil, errs.Or(err, errs.ErrOperationFailed)
|
||||
}
|
||||
|
||||
statisticAssetTrendsResp := make(models.TransactionStatisticAssetTrendsResponseItemSlice, 0)
|
||||
|
||||
for yearMonthDay, dailyAccountBalances := range accountDailyBalances {
|
||||
dailyStatisticResp := &models.TransactionStatisticAssetTrendsResponseItem{
|
||||
Year: yearMonthDay / 10000,
|
||||
Month: (yearMonthDay % 10000) / 100,
|
||||
Day: yearMonthDay % 100,
|
||||
Items: make([]*models.TransactionStatisticAssetTrendsResponseDataItem, len(dailyAccountBalances)),
|
||||
}
|
||||
|
||||
for i := 0; i < len(dailyAccountBalances); i++ {
|
||||
accountBalance := dailyAccountBalances[i]
|
||||
dailyStatisticResp.Items[i] = &models.TransactionStatisticAssetTrendsResponseDataItem{
|
||||
AccountId: accountBalance.AccountId,
|
||||
AccountOpeningBalance: accountBalance.AccountOpeningBalance,
|
||||
AccountClosingBalance: accountBalance.AccountClosingBalance,
|
||||
}
|
||||
}
|
||||
|
||||
statisticAssetTrendsResp = append(statisticAssetTrendsResp, dailyStatisticResp)
|
||||
}
|
||||
|
||||
sort.Sort(statisticAssetTrendsResp)
|
||||
|
||||
return statisticAssetTrendsResp, nil
|
||||
}
|
||||
|
||||
// TransactionAmountsHandler returns transaction amounts of current user
|
||||
func (a *TransactionsApi) TransactionAmountsHandler(c *core.WebContext) (any, *errs.Error) {
|
||||
var transactionAmountsReq models.TransactionAmountsRequest
|
||||
|
||||
@@ -275,6 +275,12 @@ type TransactionStatisticTrendsRequest struct {
|
||||
UseTransactionTimezone bool `form:"use_transaction_timezone"`
|
||||
}
|
||||
|
||||
// TransactionStatisticAssetTrendsRequest represents all parameters of transaction statistic asset trends request
|
||||
type TransactionStatisticAssetTrendsRequest struct {
|
||||
StartTime int64 `form:"start_time"`
|
||||
EndTime int64 `form:"end_time"`
|
||||
}
|
||||
|
||||
// TransactionAmountsRequest represents all parameters of transaction amounts request
|
||||
type TransactionAmountsRequest struct {
|
||||
Query string `form:"query"`
|
||||
@@ -403,6 +409,21 @@ type TransactionStatisticTrendsResponseItem struct {
|
||||
Items []*TransactionStatisticResponseItem `json:"items"`
|
||||
}
|
||||
|
||||
// TransactionStatisticAssetTrendsResponseItem represents the data within each statistic interval
|
||||
type TransactionStatisticAssetTrendsResponseItem struct {
|
||||
Year int32 `json:"year"`
|
||||
Month int32 `json:"month"`
|
||||
Day int32 `json:"day"`
|
||||
Items []*TransactionStatisticAssetTrendsResponseDataItem `json:"items"`
|
||||
}
|
||||
|
||||
// TransactionStatisticAssetTrendsResponseDataItem represents an asset trends data item
|
||||
type TransactionStatisticAssetTrendsResponseDataItem struct {
|
||||
AccountId int64 `json:"accountId,string"`
|
||||
AccountOpeningBalance int64 `json:"accountOpeningBalance"`
|
||||
AccountClosingBalance int64 `json:"accountClosingBalance"`
|
||||
}
|
||||
|
||||
// TransactionAmountsResponseItem represents an item of transaction amounts
|
||||
type TransactionAmountsResponseItem struct {
|
||||
StartTime int64 `json:"startTime"`
|
||||
@@ -600,6 +621,32 @@ func (s TransactionStatisticTrendsResponseItemSlice) Less(i, j int) bool {
|
||||
return s[i].Month < s[j].Month
|
||||
}
|
||||
|
||||
// TransactionStatisticAssetTrendsResponseItemSlice represents the slice data structure of TransactionStatisticAssetTrendsResponseItem
|
||||
type TransactionStatisticAssetTrendsResponseItemSlice []*TransactionStatisticAssetTrendsResponseItem
|
||||
|
||||
// Len returns the count of items
|
||||
func (s TransactionStatisticAssetTrendsResponseItemSlice) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
// Swap swaps two items
|
||||
func (s TransactionStatisticAssetTrendsResponseItemSlice) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
// Less reports whether the first item is less than the second one
|
||||
func (s TransactionStatisticAssetTrendsResponseItemSlice) Less(i, j int) bool {
|
||||
if s[i].Year != s[j].Year {
|
||||
return s[i].Year < s[j].Year
|
||||
}
|
||||
|
||||
if s[i].Month != s[j].Month {
|
||||
return s[i].Month < s[j].Month
|
||||
}
|
||||
|
||||
return s[i].Day < s[j].Day
|
||||
}
|
||||
|
||||
// TransactionAmountsResponseItemAmountInfoSlice represents the slice data structure of TransactionAmountsResponseItemAmountInfo
|
||||
type TransactionAmountsResponseItemAmountInfoSlice []*TransactionAmountsResponseItemAmountInfo
|
||||
|
||||
|
||||
@@ -164,6 +164,61 @@ func TestTransactionStatisticTrendsResponseItemSliceLess(t *testing.T) {
|
||||
assert.Equal(t, int32(9), transactionTrendsSlice[4].Month)
|
||||
}
|
||||
|
||||
func TestTransactionStatisticAssetTrendsResponseItemSliceLess(t *testing.T) {
|
||||
var transactionTrendsSlice TransactionStatisticAssetTrendsResponseItemSlice
|
||||
transactionTrendsSlice = append(transactionTrendsSlice, &TransactionStatisticAssetTrendsResponseItem{
|
||||
Year: 2024,
|
||||
Month: 9,
|
||||
Day: 1,
|
||||
})
|
||||
transactionTrendsSlice = append(transactionTrendsSlice, &TransactionStatisticAssetTrendsResponseItem{
|
||||
Year: 2024,
|
||||
Month: 9,
|
||||
Day: 2,
|
||||
})
|
||||
transactionTrendsSlice = append(transactionTrendsSlice, &TransactionStatisticAssetTrendsResponseItem{
|
||||
Year: 2024,
|
||||
Month: 10,
|
||||
Day: 1,
|
||||
})
|
||||
transactionTrendsSlice = append(transactionTrendsSlice, &TransactionStatisticAssetTrendsResponseItem{
|
||||
Year: 2022,
|
||||
Month: 10,
|
||||
Day: 1,
|
||||
})
|
||||
transactionTrendsSlice = append(transactionTrendsSlice, &TransactionStatisticAssetTrendsResponseItem{
|
||||
Year: 2023,
|
||||
Month: 1,
|
||||
Day: 1,
|
||||
})
|
||||
transactionTrendsSlice = append(transactionTrendsSlice, &TransactionStatisticAssetTrendsResponseItem{
|
||||
Year: 2024,
|
||||
Month: 2,
|
||||
Day: 2,
|
||||
})
|
||||
|
||||
sort.Sort(transactionTrendsSlice)
|
||||
|
||||
assert.Equal(t, int32(2022), transactionTrendsSlice[0].Year)
|
||||
assert.Equal(t, int32(10), transactionTrendsSlice[0].Month)
|
||||
assert.Equal(t, int32(1), transactionTrendsSlice[0].Day)
|
||||
assert.Equal(t, int32(2023), transactionTrendsSlice[1].Year)
|
||||
assert.Equal(t, int32(1), transactionTrendsSlice[1].Month)
|
||||
assert.Equal(t, int32(1), transactionTrendsSlice[1].Day)
|
||||
assert.Equal(t, int32(2024), transactionTrendsSlice[2].Year)
|
||||
assert.Equal(t, int32(2), transactionTrendsSlice[2].Month)
|
||||
assert.Equal(t, int32(2), transactionTrendsSlice[2].Day)
|
||||
assert.Equal(t, int32(2024), transactionTrendsSlice[3].Year)
|
||||
assert.Equal(t, int32(9), transactionTrendsSlice[3].Month)
|
||||
assert.Equal(t, int32(1), transactionTrendsSlice[3].Day)
|
||||
assert.Equal(t, int32(2024), transactionTrendsSlice[4].Year)
|
||||
assert.Equal(t, int32(9), transactionTrendsSlice[4].Month)
|
||||
assert.Equal(t, int32(2), transactionTrendsSlice[4].Day)
|
||||
assert.Equal(t, int32(2024), transactionTrendsSlice[5].Year)
|
||||
assert.Equal(t, int32(10), transactionTrendsSlice[5].Month)
|
||||
assert.Equal(t, int32(1), transactionTrendsSlice[5].Day)
|
||||
}
|
||||
|
||||
func TestTransactionAmountsResponseItemAmountInfoSliceLess(t *testing.T) {
|
||||
var amountInfoSlice TransactionAmountsResponseItemAmountInfoSlice
|
||||
amountInfoSlice = append(amountInfoSlice, &TransactionAmountsResponseItemAmountInfo{
|
||||
|
||||
@@ -43,6 +43,8 @@ var ALL_ALLOWED_CLOUD_SYNC_APP_SETTING_KEY_TYPES = map[string]UserApplicationClo
|
||||
"statistics.defaultCategoricalChartDataRangeType": USER_APPLICATION_CLOUD_SETTING_TYPE_NUMBER,
|
||||
"statistics.defaultTrendChartType": USER_APPLICATION_CLOUD_SETTING_TYPE_NUMBER,
|
||||
"statistics.defaultTrendChartDataRangeType": USER_APPLICATION_CLOUD_SETTING_TYPE_NUMBER,
|
||||
"statistics.defaultAssetTrendsChartType": USER_APPLICATION_CLOUD_SETTING_TYPE_NUMBER,
|
||||
"statistics.defaultAssetTrendsChartDataRangeType": USER_APPLICATION_CLOUD_SETTING_TYPE_NUMBER,
|
||||
}
|
||||
|
||||
// UserApplicationCloudSetting represents user application cloud setting stored in database
|
||||
|
||||
@@ -107,8 +107,8 @@ func (s *TransactionService) GetAllSpecifiedTransactions(c core.Context, uid int
|
||||
return allTransactions, nil
|
||||
}
|
||||
|
||||
// GetAllTransactionsWithAccountBalanceByMaxTime returns account statement within time range
|
||||
func (s *TransactionService) GetAllTransactionsWithAccountBalanceByMaxTime(c core.Context, uid int64, pageCount int32, maxTransactionTime int64, minTransactionTime int64, accountId int64, accountCategory models.AccountCategory) ([]*models.TransactionWithAccountBalance, int64, int64, int64, int64, error) {
|
||||
// GetAllTransactionsInOneAccountWithAccountBalanceByMaxTime returns account statement within time range
|
||||
func (s *TransactionService) GetAllTransactionsInOneAccountWithAccountBalanceByMaxTime(c core.Context, uid int64, pageCount int32, maxTransactionTime int64, minTransactionTime int64, accountId int64, accountCategory models.AccountCategory) ([]*models.TransactionWithAccountBalance, int64, int64, int64, int64, error) {
|
||||
if maxTransactionTime <= 0 {
|
||||
maxTransactionTime = utils.GetMaxTransactionTimeFromUnixTime(time.Now().Unix())
|
||||
}
|
||||
@@ -158,7 +158,7 @@ func (s *TransactionService) GetAllTransactionsWithAccountBalanceByMaxTime(c cor
|
||||
} else if transaction.Type == models.TRANSACTION_DB_TYPE_TRANSFER_IN {
|
||||
accumulatedBalance = accumulatedBalance + transaction.Amount
|
||||
} else {
|
||||
log.Errorf(c, "[transactions.GetAllTransactionsWithAccountBalanceByMaxTime] trasaction type (%d) is invalid (id:%d)", transaction.TransactionId, transaction.Type)
|
||||
log.Errorf(c, "[transactions.GetAllTransactionsInOneAccountWithAccountBalanceByMaxTime] trasaction type (%d) is invalid (id:%d)", transaction.TransactionId, transaction.Type)
|
||||
return nil, 0, 0, 0, 0, errs.ErrTransactionTypeInvalid
|
||||
}
|
||||
|
||||
@@ -197,6 +197,132 @@ func (s *TransactionService) GetAllTransactionsWithAccountBalanceByMaxTime(c cor
|
||||
return allTransactionsAndAccountBalance, totalInflows, totalOutflows, openingBalance, accumulatedBalance, nil
|
||||
}
|
||||
|
||||
// GetAllAccountsDailyOpeningAndClosingBalance returns daily opening and closing balance of all accounts within time range
|
||||
func (s *TransactionService) GetAllAccountsDailyOpeningAndClosingBalance(c core.Context, uid int64, maxTransactionTime int64, minTransactionTime int64, utcOffset int16) (map[int32][]*models.TransactionWithAccountBalance, error) {
|
||||
if maxTransactionTime <= 0 {
|
||||
maxTransactionTime = utils.GetMaxTransactionTimeFromUnixTime(time.Now().Unix())
|
||||
}
|
||||
|
||||
clientLocation := time.FixedZone("Client Timezone", int(utcOffset)*60)
|
||||
var allTransactions []*models.Transaction
|
||||
|
||||
for maxTransactionTime > 0 {
|
||||
transactions, err := s.GetTransactionsByMaxTime(c, uid, maxTransactionTime, 0, 0, nil, nil, nil, false, models.TRANSACTION_TAG_FILTER_HAS_ANY, "", "", 1, pageCountForLoadTransactionAmounts, false, false)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
allTransactions = append(allTransactions, transactions...)
|
||||
|
||||
if len(transactions) < pageCountForLoadTransactionAmounts {
|
||||
maxTransactionTime = 0
|
||||
break
|
||||
}
|
||||
|
||||
maxTransactionTime = transactions[len(transactions)-1].TransactionTime - 1
|
||||
}
|
||||
|
||||
accountDailyLastBalances := make(map[string]*models.TransactionWithAccountBalance)
|
||||
accountDailyBalances := make(map[int32][]*models.TransactionWithAccountBalance)
|
||||
|
||||
if len(allTransactions) < 1 {
|
||||
return accountDailyBalances, nil
|
||||
}
|
||||
|
||||
accumulatedBalances := make(map[int64]int64)
|
||||
accumulatedBalancesBeforeStartTime := make(map[int64]int64)
|
||||
|
||||
for i := len(allTransactions) - 1; i >= 0; i-- {
|
||||
transaction := allTransactions[i]
|
||||
accumulatedBalance := accumulatedBalances[transaction.AccountId]
|
||||
lastAccumulatedBalance := accumulatedBalances[transaction.AccountId]
|
||||
|
||||
if transaction.Type == models.TRANSACTION_DB_TYPE_MODIFY_BALANCE {
|
||||
accumulatedBalance = accumulatedBalance + transaction.RelatedAccountAmount
|
||||
} else if transaction.Type == models.TRANSACTION_DB_TYPE_INCOME {
|
||||
accumulatedBalance = accumulatedBalance + transaction.Amount
|
||||
} else if transaction.Type == models.TRANSACTION_DB_TYPE_EXPENSE {
|
||||
accumulatedBalance = accumulatedBalance - transaction.Amount
|
||||
} else if transaction.Type == models.TRANSACTION_DB_TYPE_TRANSFER_OUT {
|
||||
accumulatedBalance = accumulatedBalance - transaction.Amount
|
||||
} else if transaction.Type == models.TRANSACTION_DB_TYPE_TRANSFER_IN {
|
||||
accumulatedBalance = accumulatedBalance + transaction.Amount
|
||||
} else {
|
||||
log.Errorf(c, "[transactions.GetAllTransactionsWithAccountBalanceByMaxTime] trasaction type (%d) is invalid (id:%d)", transaction.TransactionId, transaction.Type)
|
||||
return nil, errs.ErrTransactionTypeInvalid
|
||||
}
|
||||
|
||||
accumulatedBalances[transaction.AccountId] = accumulatedBalance
|
||||
|
||||
if transaction.TransactionTime < minTransactionTime {
|
||||
accumulatedBalancesBeforeStartTime[transaction.AccountId] = accumulatedBalance
|
||||
continue
|
||||
}
|
||||
|
||||
yearMonthDay := utils.FormatUnixTimeToNumericYearMonthDay(utils.GetUnixTimeFromTransactionTime(transaction.TransactionTime), clientLocation)
|
||||
groupKey := fmt.Sprintf("%d_%d", yearMonthDay, transaction.AccountId)
|
||||
dailyAccountBalance, exists := accountDailyLastBalances[groupKey]
|
||||
|
||||
if exists {
|
||||
dailyAccountBalance.AccountClosingBalance = accumulatedBalance
|
||||
} else {
|
||||
dailyAccountBalance = &models.TransactionWithAccountBalance{
|
||||
Transaction: &models.Transaction{
|
||||
AccountId: transaction.AccountId,
|
||||
},
|
||||
AccountOpeningBalance: lastAccumulatedBalance,
|
||||
AccountClosingBalance: accumulatedBalance,
|
||||
}
|
||||
accountDailyLastBalances[groupKey] = dailyAccountBalance
|
||||
}
|
||||
}
|
||||
|
||||
firstTransactionTime := allTransactions[len(allTransactions)-1].TransactionTime
|
||||
|
||||
if minTransactionTime > firstTransactionTime {
|
||||
firstTransactionTime = minTransactionTime
|
||||
}
|
||||
|
||||
firstYearMonthDay := utils.FormatUnixTimeToNumericYearMonthDay(utils.GetUnixTimeFromTransactionTime(firstTransactionTime), clientLocation)
|
||||
|
||||
// fill in the opening balance for accounts that do not have transactions on the first day
|
||||
for accountId, accumulatedBalance := range accumulatedBalancesBeforeStartTime {
|
||||
if accumulatedBalance == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
groupKey := fmt.Sprintf("%d_%d", firstYearMonthDay, accountId)
|
||||
|
||||
if _, exists := accountDailyLastBalances[groupKey]; exists {
|
||||
continue
|
||||
}
|
||||
|
||||
accountDailyLastBalances[groupKey] = &models.TransactionWithAccountBalance{
|
||||
Transaction: &models.Transaction{
|
||||
AccountId: accountId,
|
||||
},
|
||||
AccountOpeningBalance: accumulatedBalance,
|
||||
AccountClosingBalance: accumulatedBalance,
|
||||
}
|
||||
}
|
||||
|
||||
for groupKey, transactionWithAccountBalance := range accountDailyLastBalances {
|
||||
groupKeyParts := strings.Split(groupKey, "_")
|
||||
yearMonthDay, _ := utils.StringToInt32(groupKeyParts[0])
|
||||
dailyAccountBalances, exists := accountDailyBalances[yearMonthDay]
|
||||
|
||||
if !exists {
|
||||
dailyAccountBalances = make([]*models.TransactionWithAccountBalance, 0)
|
||||
}
|
||||
|
||||
dailyAccountBalances = append(dailyAccountBalances, transactionWithAccountBalance)
|
||||
accountDailyBalances[yearMonthDay] = dailyAccountBalances
|
||||
}
|
||||
|
||||
return accountDailyBalances, nil
|
||||
}
|
||||
|
||||
// GetTransactionsByMaxTime returns transactions before given time
|
||||
func (s *TransactionService) GetTransactionsByMaxTime(c core.Context, uid int64, maxTransactionTime int64, minTransactionTime int64, transactionType models.TransactionType, categoryIds []int64, accountIds []int64, tagIds []int64, noTags bool, tagFilterType models.TransactionTagFilterType, amountFilter string, keyword string, page int32, count int32, needOneMoreItem bool, noDuplicated bool) ([]*models.Transaction, error) {
|
||||
if uid <= 0 {
|
||||
|
||||
@@ -155,6 +155,17 @@ func FormatUnixTimeToNumericYearMonth(unixTime int64, timezone *time.Location) i
|
||||
return int32(t.Year())*100 + int32(t.Month())
|
||||
}
|
||||
|
||||
// FormatUnixTimeToNumericYearMonthDay returns numeric year, month and day of specified unix time
|
||||
func FormatUnixTimeToNumericYearMonthDay(unixTime int64, timezone *time.Location) int32 {
|
||||
t := parseFromUnixTime(unixTime)
|
||||
|
||||
if timezone != nil {
|
||||
t = t.In(timezone)
|
||||
}
|
||||
|
||||
return int32(t.Year())*10000 + int32(t.Month())*100 + int32(t.Day())
|
||||
}
|
||||
|
||||
// FormatUnixTimeToNumericLocalDateTime returns numeric year, month, day, hour, minute and second of specified unix time
|
||||
func FormatUnixTimeToNumericLocalDateTime(unixTime int64, timezone *time.Location) int64 {
|
||||
t := parseFromUnixTime(unixTime)
|
||||
|
||||
@@ -133,6 +133,20 @@ func TestFormatUnixTimeToNumericYearMonth(t *testing.T) {
|
||||
assert.Equal(t, expectedValue, actualValue)
|
||||
}
|
||||
|
||||
func TestFormatUnixTimeToNumericYearMonthDay(t *testing.T) {
|
||||
unixTime := int64(1617228083)
|
||||
utcTimezone := time.FixedZone("Test Timezone", 0) // UTC
|
||||
utc8Timezone := time.FixedZone("Test Timezone", 28800) // UTC+8
|
||||
|
||||
expectedValue := int32(20210331)
|
||||
actualValue := FormatUnixTimeToNumericYearMonthDay(unixTime, utcTimezone)
|
||||
assert.Equal(t, expectedValue, actualValue)
|
||||
|
||||
expectedValue = int32(20210401)
|
||||
actualValue = FormatUnixTimeToNumericYearMonthDay(unixTime, utc8Timezone)
|
||||
assert.Equal(t, expectedValue, actualValue)
|
||||
}
|
||||
|
||||
func TestFormatUnixTimeToNumericLocalDateTime(t *testing.T) {
|
||||
unixTime := int64(1617228083)
|
||||
utcTimezone := time.FixedZone("Test Timezone", 0) // UTC
|
||||
|
||||
Reference in New Issue
Block a user